package com.lds.register.center.server.business.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lds.management.center.common.model.db.OrderBy;
import com.lds.management.center.common.model.db.PageResult;
import com.lds.management.center.common.model.dto.ResultDTO;
import com.lds.register.center.common.model.app.request.AppBaseBatchCreateRequest;
import com.lds.register.center.common.model.app.request.AppBaseBatchDeleteRequest;
import com.lds.register.center.common.model.app.request.AppBaseBatchUpdateRequest;
import com.lds.register.center.common.model.app.request.AppBaseCreateRequest;
import com.lds.register.center.common.model.app.request.AppBaseDeleteRequest;
import com.lds.register.center.common.model.app.request.AppBaseGetByIdRequest;
import com.lds.register.center.common.model.app.request.AppBaseGetByIdsRequest;
import com.lds.register.center.common.model.app.request.AppBaseGetByKeyRequest;
import com.lds.register.center.common.model.app.request.AppBaseListPageRequest;
import com.lds.register.center.common.model.app.request.AppBaseListRequest;
import com.lds.register.center.common.model.app.request.AppBaseUpdateRequest;
import com.lds.register.center.common.model.app.response.AppBaseBatchCreateResponse;
import com.lds.register.center.common.model.app.response.AppBaseBatchDeleteResponse;
import com.lds.register.center.common.model.app.response.AppBaseBatchUpdateResponse;
import com.lds.register.center.common.model.app.response.AppBaseDeleteResponse;
import com.lds.register.center.common.model.app.response.AppBaseListResponse;
import com.lds.register.center.common.model.app.response.AppBaseResponse;
import com.lds.register.center.server.business.app.converter.AppBaseCreateRequestToEntityConverter;
import com.lds.register.center.server.business.app.converter.AppBaseGetByKeyRequestToEntityConverter;
import com.lds.register.center.server.business.app.converter.AppBaseListPageRequestToEntityConverter;
import com.lds.register.center.server.business.app.converter.AppBaseListRequestToEntityConverter;
import com.lds.register.center.server.business.app.converter.AppBaseUpdateRequestToEntityConverter;
import com.lds.register.center.server.business.app.converter.AppToBaseResponseConverter;
import com.lds.register.center.server.business.app.entity.App;
import com.lds.register.center.server.business.app.mapper.AppMapper;
import com.lds.register.center.server.business.app.service.AppBaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 基础服务实现类
 *
 * @author lidongsheng
 * @since 2025-06-26
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AppBaseServiceImpl implements AppBaseService {
    private final AppMapper appMapper;
    private final AppBaseCreateRequestToEntityConverter appBaseCreateRequestToEntityConverter;
    private final AppBaseUpdateRequestToEntityConverter appBaseUpdateRequestToEntityConverter;
    private final AppBaseListRequestToEntityConverter appBaseListRequestToEntityConverter;
    private final AppToBaseResponseConverter appToBaseResponseConverter;
    private final AppBaseListPageRequestToEntityConverter appBaseListPageRequestToEntityConverter;
    private final AppBaseGetByKeyRequestToEntityConverter appBaseGetByKeyRequestToEntityConverter;

    @Override
    @Transactional
    public ResultDTO<AppBaseResponse> createApp(AppBaseCreateRequest request) {
        try {
            App app = appBaseCreateRequestToEntityConverter.convert(request);
            appMapper.insert(app);
            AppBaseResponse response = appToBaseResponseConverter.convert(app);
            return ResultDTO.success(response);
        } catch (DuplicateKeyException e) {
            return ResultDTO.fail("DATA_REPEAT", "数据重复");
        }
    }

    @Transactional
    @Override
    public ResultDTO<AppBaseBatchCreateResponse> batchCreateApp(AppBaseBatchCreateRequest request) {
        AppBaseBatchCreateResponse response = AppBaseBatchCreateResponse.builder()
                .responses(request.getRequests().stream().map(this::createApp).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<AppBaseDeleteResponse> deleteApp(AppBaseDeleteRequest request) {
        // namespace引用关系

        appMapper.deleteById(request.getId());

        AppBaseDeleteResponse response = AppBaseDeleteResponse.builder().request(request).build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<AppBaseBatchDeleteResponse> batchDeleteApp(AppBaseBatchDeleteRequest request) {
        AppBaseBatchDeleteResponse response = AppBaseBatchDeleteResponse.builder()
                .responses(request.getRequests().stream().map(this::deleteApp).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Transactional
    @Override
    public ResultDTO<AppBaseResponse> updateApp(AppBaseUpdateRequest request) {
        try {
            App app = appBaseUpdateRequestToEntityConverter.convert(request);
            appMapper.updateById(app);
            AppBaseResponse response = appToBaseResponseConverter.convert(app);
            return ResultDTO.success(response);
        } catch (DuplicateKeyException e) {
            return ResultDTO.fail("DATA_REPEAT", "数据重复");
        }
    }

    @Transactional
    @Override
    public ResultDTO<AppBaseBatchUpdateResponse> batchUpdateApp(AppBaseBatchUpdateRequest request) {
        AppBaseBatchUpdateResponse response = AppBaseBatchUpdateResponse.builder()
                .requests(request.getRequests().stream().map(this::updateApp).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<AppBaseResponse> getAppById(AppBaseGetByIdRequest request) {
        App app = appMapper.selectById(request.getId());
        if (app == null) {
            return ResultDTO.success();
        }

        AppBaseResponse response = appToBaseResponseConverter.convert(app);
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<AppBaseListResponse> getAppByIds(AppBaseGetByIdsRequest request) {
        List<App> list = request.getIds().stream().map(id -> appMapper.selectById(id)).collect(Collectors.toList());
        return ResultDTO.success(AppBaseListResponse.builder()
                .apps(list.stream().map(app -> appToBaseResponseConverter.convert(app)).collect(Collectors.toList()))
                .build());
    }

    @Override
    public App getAppByKey(AppBaseGetByKeyRequest request) {
        return appMapper.selectOne(new QueryWrapper<>(appBaseGetByKeyRequestToEntityConverter.convert(request)));
    }

    @Override
    public ResultDTO<AppBaseListResponse> listApp(AppBaseListRequest request) {
        QueryWrapper<App> wrapper = new QueryWrapper<>(appBaseListRequestToEntityConverter.convert(request));
        if (StringUtils.isNotEmpty(request.getOrderByKey())) {
            wrapper.orderByDesc(request.getOrderByKey());
        }

        List<App> apps = appMapper.selectList(wrapper);

        AppBaseListResponse response = AppBaseListResponse.builder()
                .apps(apps.stream().map(appToBaseResponseConverter::convert).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<AppBaseListResponse> listAllApp(OrderBy orderBy) {
        AppBaseListRequest appRequest = AppBaseListRequest.builder().build();
        appRequest.setOrderByKey(orderBy.getOrderByKey());
        return listApp(appRequest);
    }

    @Override
    public ResultDTO<PageResult<AppBaseResponse>> listAppPage(AppBaseListPageRequest request) {
        Page<App> page = new Page<>(request.getPageNum(), request.getPageSize(), true);

        QueryWrapper<App> wrapper = new QueryWrapper<>(appBaseListPageRequestToEntityConverter.convert(request));
        if (StringUtils.isNotEmpty(request.getOrderByKey())) {
            if (request.getOrderByDesc() != null && !request.getOrderByDesc()) {
                wrapper.orderByAsc(request.getOrderByKey());
            } else {
                wrapper.orderByDesc(request.getOrderByKey());
            }
        }

        IPage<App> pageResult = appMapper.selectPage(page, wrapper);

        PageResult<AppBaseResponse> response = new PageResult(
                pageResult.getTotal(), pageResult.getPages(), pageResult.getCurrent(), pageResult.getSize(),
                pageResult.getRecords().stream().map(appToBaseResponseConverter::convert).collect(Collectors.toList()));
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<AppBaseBatchCreateResponse> batchCreateAppAsync(AppBaseBatchCreateRequest request) {
        AppBaseBatchCreateResponse response = AppBaseBatchCreateResponse.builder()
                .responses(request.getRequests().parallelStream().map(this::createApp).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<AppBaseBatchDeleteResponse> batchDeleteAppAsync(AppBaseBatchDeleteRequest request) {
        AppBaseBatchDeleteResponse response = AppBaseBatchDeleteResponse.builder()
                .responses(request.getRequests().parallelStream().map(this::deleteApp).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

    @Override
    public ResultDTO<AppBaseBatchUpdateResponse> batchUpdateAppAsync(AppBaseBatchUpdateRequest request) {
        AppBaseBatchUpdateResponse response = AppBaseBatchUpdateResponse.builder()
                .requests(request.getRequests().parallelStream().map(this::updateApp).collect(Collectors.toList()))
                .build();
        return ResultDTO.success(response);
    }

}
